package com.itheima.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.config.ParamConfig;
import com.itheima.dto.DishDto;
import com.itheima.po.*;
import com.itheima.service.*;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author Andy
 * @Description //TODO EmployeeController
 * @Date 2022/3/8 10:59 上午
 * @Version 1.0
 **/
@RequestMapping("/dish")
@RestController
public class DishController {

    @Autowired
    private DishServcie dishServcie;

    @Autowired
    private DishFLavorServcie dishFLavorServcie;

    @Autowired
    private CatetoryService catetoryService;

    @Autowired
    private SetmealServcie setmealServcie;

//    四次交互
//    1 菜品分类数据获取
//    2 3 图片上传下载
//    4 菜品数据保存 DishDto

    @PostMapping("")
    public R<String> save(@RequestBody DishDto dishDto){
//
        dishServcie.saveWithFlavor(dishDto);
        String key = "dish_list_by_" + dishDto.getCategoryId() + "_and_" + dishDto.getStatus();
        redisTemplate.delete(key);
        return R.success("添加成功");
    }


    @GetMapping("/page")
    public R<Page<DishDto>> page(Integer page, Integer pageSize, String name){
//        根据查询条件查询出菜品数据
        Page<Dish> dishPage = new Page<>(page, pageSize); // 从数据库中查询出来
        LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        "" " " null "     "
        lambdaQueryWrapper.like(StringUtils.isNotBlank(name), Dish::getName, name);
        dishServcie.page(dishPage, lambdaQueryWrapper);
//        根据菜品数据中的分类ID查询分类数据
//        把Dish的值复制给DishDto
//       因为 dishPage没有categoryName，所以需要把dishPage的值复制给dishDtoPage

        Page<DishDto> dishDtoPage = new Page<>(); // 真正要返回给前端的
       /* dishDtoPage.setRecords(new ArrayList<>());
//        从数据库中差回来的分页的dish数据
        List<Dish> records = dishPage.getRecords();
        for (int i =0 ; i< records.size();i++){
            DishDto dishDto = new DishDto();
            dishDto.setCategoryId(records.get(i).getCategoryId());
            dishDto.setImage(records.get(i).getImage());
            dishDto.setCategoryId(records.get(i).getCategoryId());
            dishDto.setCategoryId(records.get(i).getCategoryId());
            dishDto.setCategoryId(records.get(i).getCategoryId());
            dishDto.setCategoryId(records.get(i).getCategoryId());
            dishDtoPage.getRecords().add(dishDto);
        }
        dishDtoPage.setTotal(dishPage.getTotal());
        dishDtoPage.setCurrent(dishPage.getCurrent());
        dishDtoPage.setSize(dishPage.getSize());

        */
//        忽略records，那么复制完后records没有复制过来，所以后面需要单独处理records的值
        BeanUtils.copyProperties(dishPage, dishDtoPage, "records");
//        虽然Page<DishDto> dishDtoPage = new Page<>(); 在初始化的时候records设置了初始值，但是并
//        不是new ArrayList<>()，所以在添加的时候报错。
        dishDtoPage.setRecords(new ArrayList<>());
//        给每个菜品的DTO设置分类名字
        List<Dish> records = dishPage.getRecords();
        for (Dish dish : records) {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            Category category = catetoryService.getById(dishDto.getCategoryId());
            if (null != category){
                dishDto.setCategoryName(category.getName());
            }
            dishDtoPage.getRecords().add(dishDto);
        }

        return R.success(dishDtoPage);
    }

//     2. 修改菜品:
//            (1) 用户点击修改,通过菜品的某一字段查询菜品信息
//            (2) 根据查询到的数据回显给前端,由前端展示在页面上
//              (3) 用户修改完数据后点击保存,将数据传到后端
//            (4) 后端人员接收数据,补充操作的实时时间和操作人员的信息
//    ------------- 5 6 7 复用CommonController
//              (5) 判断修改后图片大小是否超过2M,如果超过则提示图片不能大于2M
//            (6) 判断修改后的图片格式是否为PNG JPEG JPG类型,如果不是则提示仅支持PNG JPEG JPG类型
//              (7) 判断修改后的图片是否与数据库中已存的名称相同
//    --------------
//            (8) 后端人员将数据保存到数据库,覆盖原有数据 dish覆盖 dish_flavor 先删后插入
//              (9) 将修改成功字段响应给前端


    @GetMapping("/{id}")
    public R<DishDto> getById(@PathVariable Long id){

//        查询菜品数据
        Dish dish = dishServcie.getById(id);
//        根据菜品ID查询口味数据
        LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DishFlavor::getDishId, dish.getId());
        List<DishFlavor> dishFlavorList = dishFLavorServcie.list(lambdaQueryWrapper);
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish, dishDto);
        dishDto.setFlavors(dishFlavorList);
        return R.success(dishDto);
    }

    @PutMapping()
    public R<String> update(@RequestBody DishDto dishDto){
        dishServcie.updateWithFlavor(dishDto);
        String key = "dish_list_by_" + dishDto.getCategoryId() + "_and_" + dishDto.getStatus();
        redisTemplate.delete(key);
        return R.success("更新成功");
    }

    @Autowired
    private SetmealDishServcie setmealDishServcie;

//    可以通过这种方式进行测试 不用造那么多数据了
//    @Value("${dish.max.delete.number}")
//    private int maxDeleteNumber;

    @DeleteMapping
//    public R<String> delete(Integer[] ids){
    public R<String> delete(@RequestParam List<Long> ids){

//        这种写法是不符合阿里巴巴代码规约的，因为在for循环或者while循环中，特别是循环的次数不定，
//        对于循环来说是一种线性行为 例如 ids的size是10 只循环10次 如果是10万 那这个方法就废了 会一直卡在这里执行
//        所以在企业开发中，如果有code review(代码审查 你的同事或领导一起review你的代码 review 相当于重新看的意思)
//        一般在企业中批量处理要怎么处理，首先不能用for循环逐条的处理，但是可以按照ids的个数进行分批，然后可以对每一批
//        进行处理
//        String[] split = ids.split(",");
//
//        List<Integer> idList = Arrays.asList(split);
//        步骤：根据ids查询出所有的菜品，然后看每一个菜品是否状态为禁售
//        超过2000作用，避免请求的数据量太大，非法使用，把服务换成占满
        if (ids.size() > 2000){
            return R.error("当删除操作发生时，超过最大删除条数限制。");
        }
//        批处理查询
        //        查询的话 500
        List<List<Long>> listPerBatch = ListUtils.partition(ids, 500);
        for (List<Long> idList :
                listPerBatch) {
            List<Dish> list = dishServcie.list(new LambdaQueryWrapper<Dish>().in(Dish::getId, idList));
            for (Dish dish :
                    list) {
                if (dish.getStatus() == 1) {
                    return R.error("有菜品状态为售卖中，无法删除");
                }
            }
//        根据所有的菜品ID进行查询，看是否有菜品被套餐使用
            LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(SetmealDish::getDishId, idList);
            int count = setmealDishServcie.count(lambdaQueryWrapper);
//        如果count > 0 说明有套餐在使用菜品
            if (count > 0){
                return R.error("有菜品正在被套餐使用，无法删除，或请先删除套餐");
            }
        }
// 批处理 删除
        dishServcie.deleteWithFlavor(ids);
//        正确错误分界线******************************上为正确 下为错误
//        下面注释掉的代码为不符合行业规范的代码 大家近作参考，切勿模仿
//        for (Integer id : ids) {
//            //        状态 有没有被套餐使用
//            Dish dish = dishServcie.getById(id);
//            if (dish.getStatus() == 1){
//                return R.error("状态为售卖中，无法删除");
//            }
////套餐有没有使用菜品？
////        setmeal_dish表中有没有dish_id被某一个套餐使用
////        select count(*) from setmeal_dish    where dish_id = #{id}
//            LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//            lambdaQueryWrapper.eq(SetmealDish::getDishId, id);
//            int count = setmealDishServcie.count(lambdaQueryWrapper);
////        如果count > 0 说明有套餐在使用菜品
//            if (count > 0){
//                return R.error("菜品正在被套餐使用，无法删除，或请先删除套餐");
//            }
////        删除菜品与删除菜品口味 涉及两张表 MySQL的事务ACID 同生共死
////        如果在controller中进行两个表删除，则无法控制事务，所以需要单独写一个service方法 并在该方法调用时
////        添加事务
//
//        }

        return R.success("删除成功");
    }
//http://localhost:8080/dish/list?categoryId=1397844263642378242
//    缺少口味数据
//Request URL: http://localhost:8080/dish/list?categoryId=1397844263642378242&status=1
//    Request Method: GET

//    步骤：
//    1. 查询出菜品数据
//    2. 根据菜品ID查询出对应的口味数据
//    3. 返回List<DishDto>
    private static final Integer DISH_SALE_STATUS = 1;
    @Autowired
    private RedisTemplate redisTemplate;
    @GetMapping("/list")
    public R<List<DishDto>> list(Long categoryId, Integer status){

        String key = "dish_list_by_" + categoryId + "_and_" + status;
//        value是什么数据结构 list
        List<DishDto> range = (List<DishDto>)redisTemplate.opsForList().range(key, 0, -1);
//        redis中有数据的时候 直接返回结果
        if (range != null && range.size() > 0){
            return R.success(range);
        }
//        如果redis中没有的时候


//        构建查询条件
        LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(null != categoryId, Dish::getCategoryId, categoryId);
        lambdaQueryWrapper.eq(null != status, Dish::getStatus, status);
        lambdaQueryWrapper.orderByAsc(Dish::getUpdateTime);
//        service触发查询
        List<Dish> list = dishServcie.list(lambdaQueryWrapper);
//        返回数据
        List<DishDto> dishDtoList = new ArrayList<>();
//        通过dish对象构建出一个dishdto对象
        for (int i =0 ; i< list.size(); i++){
            Dish dish = list.get(i);
//            根据dishid查询口味数据
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId, dish.getId());
            List<DishFlavor> dishFlavorList = dishFLavorServcie.list(dishFlavorLambdaQueryWrapper);
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            dishDto.setFlavors(dishFlavorList);
            dishDtoList.add(dishDto);
        }
        redisTemplate.opsForList().leftPushAll(key, dishDtoList);
        return R.success(dishDtoList);
    }



}
